perm filename MESSAG.WRU[SYS,HE] blob sn#004173 filedate 1972-06-01 generic text, type T, neo UTF8
00100	%TOP,,HAND-EYE SYSTEM PART II,  ,1-1
00200	 
00300	
00400	
00500	
00600	
00700	
00800	
00900	
01000	
01100	
01200	
01300	
01400	
01500	
01600			SYSTEM MANUAL FOR HAND-EYE HACKERS
01700	
01750			PART I.				[HAND.WRU]
01800			PART II.  MESSAGE PROCEDURES	[MESSAG.WRU]
01900				SECTION 1. AN EXAMPLE
02000				SECTION 2. CALLS
02100				SECTION 3. ANOTHER EXAMPLE
02200				SECTION 4. TEMPLATES
02250				SECTION 5. ERROR MESSAGES
02300			PART III. MONITOR		[MONITR.WRU]
     

00100	1.0  MESSAGE PROCEDURES
00200	
00300	There must  be  a  mechanism  for  communicating  among  the  various
00400	modules   of  the  hand-eye  system.   Since each of these modules is
00500	talking to a common second segment, it makes sense to  establish  the
00600	communication paths in that segment.
00700	
00800	We  want  to  be  able  to  send  messages  to  each other which have
00900	SAIL-like data associated with them.  We do not want to  convert  all
01000	our  message  data  to some symbolic form and (say) write a disk file
01100	with that text, but instead to pass data of all types  (sets,  items,
01200	arrays,  integers, reals, etc.) in a reasonably efficient manner.  At
01300	the same time, we want to prevent the  programs  from  having  to  do
01400	explicit  type-checking of message data, or explicit "get this datum"
01500	operations.
01600	
01700	A mechanism which meets these requirements is already in SAIL, namely
01800	actual  parameter  passing  to  procedures.   A message , then,  will
01900	consist of a name of a procedure and a parameter list to pass to that
02000	procedure for evaluation, together with some bookkeeping information.
02100	The user is allowed to specify a symbolic source of the message and a
02200	symbolic destination for the message.  These names specify the module
02300	to  be  activated (i.e. the recipient of the message), and the source
02400	module.
02500	
02600	So to review, we have implemented a  mechanism  for  a  user  in  one
02700	module  to  emit  calls  to  procedures  actually  located in another
02800	module.  The matching and passing of formal parameters is handled  in
02900	much the same way as for ordinary procedures.  Of course, the calling
03000	module must have declared  the  names  and  parameter  lists  of  the
03100	procedures  he is calling. These declarations will be in the hand eye
03200	definition tape,  and  look  like  ordinary  procedure  declarations,
03300	except that the words FORWARD MESSAGE appear:
03400	
03500	FORWARD MESSAGE PROCEDURE TRANSFORM(INTEGER X;ITEM Y;REAL ARRAY Z);
03600	
03700	Now let us shift attention to the module in which this  procedure  is
03800	actually  located.   We  must  provide  a  mechanism  to  allow  this
03900	procedure to be evaluated for each "message" passed to it.  We  could
04000	arrange  that  whenever  a  message specifying the evaluation of some
04100	procedure was passed to a module, that module is interrupted, and the
04200	message  request honored.  But this is unthinkable, for many reasons.
04300	First, the module would like to control  the  priorities  with  which
04400	messages  are  evaluated.  Second,  the  module might object to being
04500	suspended  in  the  midst  of  a  computation  which  has   left   an
04600	inconsistent view of the world in the module's data structures.
04700	
04800	To  rectify  this,  a  module must specifically receive messages, and
04900	must request the evaluation of the  specified  procedure.   The  SAIL
05000	calls for doing this are described below.
05100	
05200	Briefly, a module may look around in the list of messages in order to
05300	locate one destined for him.  He may then request that the message be
05400	activated, i.e evaluate the procedure which is located in  my  module
05500	and  which has the same name as the "procedure name" specified in the
05600	message.   This  evaluation  is  performed  with  the  arguments   as
05700	specified  in  the  message.  Normally, when the procedure exits, the
05800	message is acknowledged (i.e.  the calling module may  now  determine
05900	that the message has completed).
06000	
06100	When  the  user declares a procedure which is to process messages, he
06200	must precede that declaration with MESSAGE:
06300	
06400	MESSAGE PROCEDURE TRANSFORM (INTEGER A;ITEM x;REAL ARRAY FOO);
06500	
06600	followed by the procedure text. These procedures may be called by you
06700	in your own module in the normal way.
06800	
06900	
     

00100	1.0 An example
00200	
00300	Let  us  briefly review by giving a very simple example.  We have two
00400	modules, which we shall call symbolically CALL and ARITH.  The module
00500	CALL  wants  to activate the message procedure TRANSFORM in the ARITH
00600	module.  He does this by sending a message to ARITH, citing TRANSFORM
00700	as  the procedure name, and giving the necessary paremeters. He wants
00800	to suspend his own execution until TRANSFORM  has  been  executed  in
00900	ARITH.  So CALL says:
01000	
01100	forward message procedure TRANSFORM (integer a; real array b);
01200		comment this is needed so that the procedure names and
01300			parameter types are known during compilation of
01400			the CALL module.  These declarations will normally
01500			reside in the global definition tape.
01600	
01700	integer mess;
01800		comment this will be explained below;
01900	
02000	mess ← ISSUE ( 7,"CALL","ARITH", MESSAGE TRANSFORM (2,mine));
02100		comment This specifies a message.  The names CALL and
02200			ARITH are the source and destination logical
02300			names respectively.  The message described is
02400			TRANSFORM (2,mine).  That is, 2 and mine will
02500			be the parameters supplied when TRANSFORM is
02600			executed in ARITH.  The 7 is a code to ask that
02700			execution be suspended until the procedure
02800			TRANSFORM has finished its evaluation, and then
02900			to kill the message (erase all record of it);
03000	
03100	
03200	Now for the code in module ARITH which will process the message:
03300	
03400	forward message procedure TRANSFORM(integer a;real array b);
03500		comment This is in the definition tape, as the
03600			definition in CALL above;
03700	
03800	integer mess;
03900	
04000	message procedure TRANSFORM (integer a; real array b);
04100		begin
04200		integer i,j;
04300		for i←1 step 1 until a do b[i]←b[i]*b[a-i+1];
04400		end;
04500	
04600		comment This is the actual procedure text for TRANSFORM;
04700	
04800	
04900		comment .. in the main execution block of ARITH, we must
05000			examine the queue of messages sent to us, and
05100			then evaluate the appropriate procedure;
05200	
05300		PUT_DATA (0,0,"ARITH");
05400			comment initialization -- described below;
05500	
05600	while true do begin
05700		mess ← GET_ENTRY ('120,NULL,"ARITH",NULL);
05800			comment This waits for a message to arrive destined
05900				for ARITH.  The unique descriptor of the
06000				message is placed in mess;
06100	
06200		mess ← QUEUE ('600,mess);
06300			comment Now that we have gotten a message, we
06400				"activate" it (i.e. evaluate the procedure
06500				located in the ARITH module, and with the
06600				name and parameters specified in the message.
06700				When finished, we "acknowledge" completion of
06800				the message.  This will allow CALL to
06900				resume computation (remember -- he requested
07000				to be suspended until TRANSFORM finished);
07100	
07200	end;
07300	
07400	
07500	
07600	This completes the simple example.  There follows a  fairly  detailed
07700	description  of  the exact SAIL calls, followed by this same example,
07800	with slightly expanded comments.  Then some templates  are  given  to
07900	aid in putting together "standard" message procedure code.
     

00100	2.0  Detailed description of message procedure calls.
00200	
00300	A queue is kept in the second segment which contains all messages.  A
00400	message  consists  of  a  symbolic source identifier (10 chars max) a
00500	symbolic destination identifier (10 chars max), a  message  procedure
00600	name  (10  chars max), and the parameter list which is to be supplied
00700	to that procedure when evaluated. Associated with each entry  in  the
00800	queue  will  be  a unique number.  The user will reference entries in
00900	the queue by this number.
01000	
01100	Many of the calls on message handlers require a directive word.  This
01200	word is made up from the following bits (all explained below):
01300	
01400		DSEND		'1
01500		DWAIT		'2
01600		DKILL		'4
01700		DSOURCE		'10
01800		DDEST		'20
01900		DNAME		'40
02000		DWAITM		'100
02100		DACT		'200
02200		DACK		'400
02300		DEVERY		'2000
02400		DNOACT		'4000
02500		DRETURN		'40000
02600	
02700	The calls which the user has available to manipulate queue entries:
02800	
02900	1. Insert a thing into the queue.
03000	
03100	integ. ← ISSUE (directive,source,destination,MESSAGE kkk(param list))
03200	
03300	KKK  is  the  message procedure name to be associated with this queue
03400	entry, and param list will be passed off for inclusion in  the  queue
03500	entry.   A declaration for KKK was made in the user's program, and is
03600	assumed to be the same declaration that was used when  the  procedure
03700	was  finally  defined.   Source and destination are the strings to be
03800	included as message identifiers.  The directive bits say what  to  do
03900	with the entry --
04000		a. put it in the queue (assumed always).
04100		b. send it to the right guy (DSEND). If DNOACT is on, the 
04200			recipient is not activated.
04300		c. wait for acknowledgment on completion (DWAIT).
04400	These directive bits may be OR'ed together, and will be processed, if
04500	on,  in  the  order  a,b,c.  Integ  will  contain  the  unique number
04600	generated, and can be used to talk about  this  queue  entry  in  the
04700	future.
04800	
04900	2. Utility functions on things in the queue.
05000	
05100	integ ←	QUEUE (directive,unique number)
05200	
05300	Directive specifies --
05400		a. send it (DSEND).
05500		b. wait for completion (DWAIT).
05600		c. activate the entry (DACT).
05700		d. acknowledge the entry (DACK).
05800		e. kill the entry (DKILL).If the message is sent to another 
05900			module, killing is delayed until the message is 
06000			acknowledged.
06100	
06200	These are processed in the order a,b,c,d,e and may be OR'd  together.
06300	If  integ. is zero, there was no such queue entry. The interpretation
06400	of DSEND and DWAIT were discussed above.   DACT  specifies  that  the
06500	procedure  named  in  the  message  should  be  evaluated.   If  that
06600	procedure is defined in your module, which it should be, it  will  be
06700	evaluated.   DACK  specifies that the message should be acknowledged.
06800	If the sender was waiting for completion of the message, he will  now
06900	be allowed to proceed. If a sender was waiting for completion and you
07000	do not acknowledge, he will never be run again.
07100	
07200	string ←  GET_DATA (directive,unique number)
07300		  PUT_DATA (directive,unique number,string)
07400	integ ←	  GET_BIT (unique number)
07500	
07600	This is for looking into the message block and perhaps changing
07700	things.  The directive may specify
07800		a. source identifier
07900		b. destination identifier
08000		c. message procedure name.
08100	The directive should be 1 for a, 2 for b, and 3 for c. Note that this
08200	is   a   non-standard  use  of  the  directive  bits.    If  you  say
08300	PUT_DATA(0,0,"string") then "string" is set as your logical name.  If
08400	some  other module sends a message with destination as "string", then
08500	you will be activated.    A  statement  like  this  is  REQUIRED  for
08600	initializing  the  message  system. If you say PUT_DATA(-1,JOBNUM,"")
08700	then the logical name and job number  of  the  job  with  job  numver
08800	JOBNUM  will  be removed .  This is usually done only by the hand/eye
08900	monitor when it kills subjobs.
09000	
09100	GET_BIT returns the bits associated with an entry in the message
09200	queue.  Integer will contain the following bits:
09300		DSEND -- the message has been sent.
09400		DWAIT -- someone is waiting for completion of this message.
09500		DKILL -- this message is marked for killing when acknowledged.
09600		DACT  -- this message is active (proc. being evaluated).
09700		DACK  -- this message has been acknowledged.
09800	
09900	3. Functions for searching the queue.
10000	
10100	integ. ← GET_ENTRY (directive,source,destination,procedure name)
10200	
10300	Where the directive specifies:
10400		a. find match on source (DSOURCE).
10500		b. find match on destination (DDEST).
10600		c. find match on procedure name (DNAME).
10700			(these a-c may be OR'd together in which case the 
10800			AND of the conditions must obtain).
10900		d. if you don't find such a thing, wait for one (DWAITM).
10950			 WARNING: As the second segment is now coded, you
10975			will only be awakened (from DWAITM or the interrupt
10987			routines) when a message specifies you as its 
10993			destination.
11000		e. Continue even if DWAITM is set (DRETURN)
11100			(for use with interrupt routine only)
11200		f. look at every entry (DEVERY).  Ordinarily, messages that
11300			are not sent or are already activated are not returned
11400			by GET_ENTRY.  If DEVERY is on, all messages matching
11500			the conditions are returned.
11600	Integ. will have the unique number.  If zero, no entry was found.
11700	
11800	
11900	set ← GET_SET (directive,source,destination,procedurename)
12000	
12100	This is the same as  GET_ENTRY,  except  that  the  set  of  possible
12200	matches  is returned.  If there is no match and DWAITM is on, we will
12300	wait!   The  unique  message  numbers are put in the set.  This means
12400	that the set will be ordered by creation order of the  messages.  You
12500	will have to do CVN's on the things you get out of the set  in  order
12600	to get numbers to use as message numbers.
12700	
12800	
12900	
13000	
13100	
13200	6. Parameters.
13300	
13400	Of course  there  are  some  difficulties  in  making  all  types  of
13500	parameters  accessible  to  the  called  routine, since things in the
13600	caller's core image are not accessible  to  the  called  routine.  So
13700	behold the catalog of things we will do for parameters:
13800	
13900	a. Call by VALUE.
14000		a. algebraic things.  This is easy, we just copy the 
14100			algebraic value. Strings are included in this class.
14200		b. sets. Sets must contain solely global items. If necessary,
14300			the sets will be recopied into 2nd segment core.
14400		c. item.  If global, ok, otherwise definitely not ok.
14500		d. itemvar. same as item.  Note that if you are trying to
14600			pass a local item merely so that the called routine
14700			can obtain the datum, then why not pass the datum??
14800	
14900	b. Call by REFERENCE.
15000		a. algebraic things.  If the thing is a global of any kind,
15100			no cleverness need be invoked.  If it is a local
15200			array, a copy will be made in the 2nd segment, and
15300			deleted after the message is ACTIVATED (no string
15400			arrays).  If the thing is any other kind of non-
15500			global entity, the right thing will happen,
15600			but under no circumstances will the called procedure
15700			be able to alter the contents of that variable in your
15800			module.  If you desire to return results, they may be
15900			returned in the global model.
16000		b. sets. If global, OK.  If a local, the set is checked for
16100			non-global items and copied into 2nd segment, and
16200			deleted after activating, just as in arrays.  Under no
16300			circumstances will any call
16400			by reference of a 1st segment thing cause that thing to
16500			be changed.
16600		c. itemvar -- if global, OK.  If not, the thing is copied 
16700			into the second segment and released after ACTIVATing.
16800	
16900	b. RETURNS.
17000	Results of message procedures may of course be returned in the global
17100	model.  There will also be some way of getting at the integer or real
17200	or itemvar result of the called procedure.  Since this  is  a  little
17300	messy  to  imbed  in the ISSUE call, we may do that by providing some
17400	specific way of accessing the message results. [NOT IMPLEMENTED]
17500	
17600	
17700	
17800	
17900	7. Tracing.
18000	
18100	There is a facility for tracing  messages  passed  from  one  job  to
18200	another.  This facility is actually handled by the same program which
18300	handles the TTY-PTY operations (see section 4 below).   Presently,  a
18400	trace consists of a type-out at the controlling TTY of the form
18500	
18600	time	MESSAGE TRACE: source destination message_procedure_name args
18700	
18800	where  time  is  in  milliseconds  since midnight.  Args is a list of
18900	argument data for the message procedure.   There  is  one  string  of
19000	characters  for  each argument, seperated by blanks.   Boolean, real,
19100	and integer arguments have their values printed  (boolean  prints  as
19200	integer).  For string arguments, the string is printed, surrounded by
19300	double quotes.   Other arguments are not printed.  Instead, a  string
19400	of  characters  describing  the data type of the argument is printed.
19500	The characters printed are:
19600	
19700	I	INTEGER (or BOOLEAN)
19800	F	REAL (floating point)
19900	L	LABEL
20000	S	SET
20100	Lp	leap array (things like SET ARRAY ITEMVAR ARRAY)
20200	St	STRING
20300	It	ITEM
20400	Iv	ITEMVAR
20500	G	GLOBAL
20600	A	ARRAY
20700	R	REFERENCE
20800	V	VALUE
20900	
21000	The details of the message tracing mechanism are as follows: There is
21100	a global variable (global in the LOADER sense, not in the SAIL sense)
21200	in the second segment called TRACING.  If it is set non-zero, message
21300	tracing  is  enabled.  Every  time a message is "sent" by the message
21400	handler, a trace message is first sent to the tracing job.  When  the
21500	tracing  message  is  acknowledged,  the  original message is finally
21600	"sent" to its prescribed destination. The tracing message is  of  the
21700	form
21800	
21900		source: ""
22000		destination:"TRACE"
22100		message: TRACE ( integer message_number , pntr )
22200	
22300	The message_number  can  be  used  to  examine  the  queue  for  good
22400	information   about  the  message  being  traced  (i.e.  the  source,
22500	destination, name, parameters, etc.). Pntr points to good things  in
22600	the second segment.
22700	
22800	
     

00100	3.0  An example of message procedures and calls.
00200	
00300	CALL module :
00400	
00500	forward message procedure TRANSFORM (integer a; real array b);
00600	
00700	......
00800	
00900	comment Somewhere, module 1 needs to call TRANSFORM.  He wants to
01000		pass arguments 2 and mine to the procedure.  He wants
01100		to wait for the evaluation to finish before continuing
01200		any of his computation.  He says:
01300	
01400	mess ← ISSUE (7,"CALL","ARITH",MESSAGE TRANSFORM (2,mine));
01500	
01600	comment This is a message from the symbolic CALL to the symbolic
01700		ARITH, and is a request for the evaluation of the 
01800		procedure TRANSFORM.  When the evaluation of TRANSFORM
01900		is complete, execution will continue with the next
02000		statement, and mess will contain the unique number
02100		associated with the message that was generated
02200		(this is useful in referring to the message if you
02300		desire to inquire as to the status of completion, etc.
02400		In this example, however, it is useless since we do not
02500		continue computation until TRANSFORM has completed, and
02600		the message has served its purpose).
02700	
02800	
02900	ARITH module:
03000	
03100	forward message procedure TRANSFORM (integer a;real array b);
03200	
03300	......
03400	comment Now he actually defines the procedure:;
03500	
03600	message procedure TRANSFORM (integer a;real array b);
03700	begin
03800		integer i,j;
03900		for i←1 step 1 until a do b[i]←b[i]*b[a-i+1];
04000	end;
04100	
04200	..... comment now in main execution block.;
04300	
04400		PUT_DATA (0,0,"ARITH");
04500	comment only needs doing once;
04600	
04700	mess ← GET_ENTRY ('120,NULL,"ARITH",NULL);
04800	
04900	comment This waits for a message sent to symbolic destination ARITH.
05000		When such a message arrives, the unique number describing
05100		that message is stored in mess.  Execution continues: ;
05200	
05300	mess ← QUEUE('600,mess);
05400	
05500	comment Now we actually activate the message.  The procedure TRANSFORM
05600		is evaluated with arguments 2,mine (or actually a copy of mine).
05700		When the procedure returns, the message is acknowledged so that
05800		module 1 can resume processing (since he decided to wait for
05900		completion).  Control in module 2 returns to the next statement:;
06000	
06100	.......
06200	
     

00100	4.0  Templates for message procedure protocol.
00200	
00300	
00400	First we give some protocols for ISSUEing message requests.  We  give
00500	the symbolic form of the directive to be used in the ISSUE call:
00600	
00700	DSEND+DWAIT+DKILL	-- normal "subroutine"-like call.
00800		You will be suspended until the destination module has
00900		processed and ACKNOWLEDGED this message.  You should
01000		check with him or his code to be sure than an acknowledgement
01100		is generated.  If it is not, you will wait a long, long
01200		time. The message is killed when done.
01300	
01400	DSEND+DKILL		-- "fork" call.
01500		You will continue execution immediately, and not wait
01600		for the destination module to to anything.  However,
01700		he should eventually get around to ACKNOWLEDGing
01800		the message, at which time it will be killed.
01900	
02000	DSEND			-- "leave mail" call.
02100		This merely puts the message in the queue.
02200		The destination job can do with this as he likes.
02300		(This can be used for passing off several messages in
02400		a row -- they need never be actually ACTIVATED or
02500		ACKNOWLEDGED by the destination).
02600	
02700	
02800	Now we give similar protocols for answering the messages. If we  rely
02900	on blind faith, and want to process each message as it arrives:
03000	
03100	mess← GET_ENTRY (DDEST+DWAITM,"","MY NAME","");
03200	
03300	Then, when this returns, we ACTIVATE and ACKNOWLEDGE the message:
03400	
03500	mess ← QUEUE (DACT+DACK,mess);
03600	if mess=0 then type "error in messages to MY NAME" eom;
03700	
03800	This will handle all  messages  ISSUEd  with  the  first  and  second
03900	protocols listed above.
     

00100	5.0	ERROR MESSAGES
00150	
00200	Below is a list of the error messages generated by the second segment
00300	message procedure routines.   The errors  will  try  to  continue  if
00400	requested  to,  but they should be considered fatal. (In other words,
00500	don't continue)
00600	
00700	MESSAGE CONFUSION		code is garbaged or second seg. bug
00800	ITEM MUST BE GLOBAL		local item was seen as an argument.
00900	NO CORE FOR MESSAGE		system is out of core
01000	THESE ARRAYS TOO COMPICATED	tried to pass set or string array
01100	TOO MANY PARAMS			over six arguments for procedure
01200	NO SUCH DESTINATION		Message sent to non-ex job
01300	MAIL WAIT CONFLICT		bug in second segment or core garbaged
01600	MAIL SCREW			The system mail mechanism goofed
01610					or two jobs of the same name exist in
01655					the system.
01700	NO DIRECTIVE			Queue called with no legal directive
01800	NO GET_ENTRY DIRECTIVE			same
01900	GET_SET:NEED LEAP INITIALIZATION  ran out of items
02000	LOGICAL NAME ALREADY DEFINED	PUT_DATA(0,0,"name") has a name already
02100					defined for another job number.  If
02150					you continue, the current job number
02175					is substituted for the old one (which
02187					may not be what you want).
02200	TOO MANY JOBS			Tables have overflowed (16 jobs allowed)
02300					If you see this message, you might
02400					inquire of the system hackers where the
02500					other PTY came from.
02600	WHO ARE YOU??			You executed a GET_ENTRY procedure
02650					before doing your PUT_DATA
02750					initialization.
02800	YOUR MESSAGE DISAPPEARED	The message you just activated was
02850					gobbled up by someone while you were
02950					executing it. This is legal but
03050					undesireable - let me know if
03150					it happens. It will continue automatically.
03200	MESSAGE SNATCHER		This is the guy who is trying to kill the
03300					above message (if it will result in core
03400					lossage).  You can continue from this
03500					message.
03600	VERSION # TOO LOW		Subjob using PREAMB.SAI has the incorrect
03700					version number.  Recompile it to get the
03800					current version of the preamble.
03900	VERSION # TOO HIGH		Either the hand/eye monitor needs to be
04000					recompiled or you have a saved second
04100					segment which is too old.